# -*- coding: utf-8 -*-
"""
===============================
@Author     : Zuo WenTao
@Time       : 2024/11/1 17:06
@Description: 
@Change     : 
@File       : LoginForBaiLian.py
===============================
"""
import sys
import platform


if platform.system().lower() == 'linux':
    sys.path.append("/home/zuo/26_DocumentDelivery/")
import Api.Proxy

import base64
import hashlib
import json
import os
import platform
import random
import re
import time
import uuid
import ddddocr

import requests

from loguru import logger

from Api.retry_model import MyRetry
from Config.Emails import emails
from Api.BookAccountNumberManage.redis_client import redis_client
from Api.Proxy_long import Proxy_IP

redis_client = redis_client.redis_pool


def getMd5(n: str):
    return hashlib.md5(n.encode()).hexdigest()


def getNonce():
    eList = []
    ostring = '0123456789abcdef'
    for i in range(36):
        eList.append(ostring[random.randint(0, 15)])
    eList[14] = '4'
    eList[19] = ostring[(int(eList[19], 16) & 3) | 8]
    eList[8] = eList[13] = eList[18] = eList[23] = '-'
    return "".join(eList)


class LoginForBaiLian:
    def __init__(self):
        self.headers = {
            "Accept": "*/*",
            "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
            "Connection": "keep-alive",
            "Referer": "https://www.blyun.com/",
            "Sec-Fetch-Dest": "script",
            "Sec-Fetch-Mode": "no-cors",
            "Sec-Fetch-Site": "cross-site",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0",
            "sec-ch-ua": "\"Chromium\";v=\"130\", \"Microsoft Edge\";v=\"130\", \"Not?A_Brand\";v=\"99\"",
            "sec-ch-ua-mobile": "?0",
            "sec-ch-ua-platform": "\"Windows\""
        }

    def add_cookie(self, username, cookie):
        if "vc3" in cookie:
            redis_client.set(f'bailian_cookie:{username}', json.dumps(cookie), ex=int(4 * 60 * 60))
            return True
        else:
            return False

    def string_to_base64(self, input_string):
        bytes_string = input_string.encode('utf-8')
        base64_bytes = base64.b64encode(bytes_string)
        base64_string = base64_bytes.decode('utf-8')
        return base64_string

    def recognize_slider_captcha(self, slider_img_url, background_img_url):
        def download_image(url, save_path):
            try:
                response = requests.get(url, headers=self.headers)
                response.raise_for_status()
                with open(save_path, 'wb') as f:
                    f.write(response.content)
                return True
            except requests.RequestException as e:
                return False

        def read_image(path):
            try:
                with open(path, 'rb') as f:
                    return f.read()
            except IOError as e:
                return None

        path = rf"D:\yingke\data\slider\{uuid.uuid4()}" if platform.system().lower() != 'linux' else rf"/mnt/slider/{uuid.uuid4()}"
        os.makedirs(path, exist_ok=True)

        slider_path = os.path.join(path, 'slider.jpg')
        background_path = os.path.join(path, 'background.jpg')

        if not download_image(slider_img_url, slider_path):
            return None
        if not download_image(background_img_url, background_path):
            return None

        slider_img = read_image(slider_path)
        background_img = read_image(background_path)

        if slider_img is None or background_img is None:
            return None

        det = ddddocr.DdddOcr(det=False, ocr=False, show_ad=False)

        position = det.slide_match(target_bytes=slider_img, background_bytes=background_img, simple_target=True)

        if position is not None:
            return position
        else:
            return None

    @MyRetry(times=3)
    def login(self, username, password):
        S = requests.Session()
        url = "https://www.blyun.com/login.jsp"
        S.proxies = Proxy_IP.get_proxy(Type="L")
        # S.proxies = {'https': 'http://YingKe:%yk123456%..@192.168.44.10:6231','http': 'http://YingKe:%yk123456%..@192.168.44.10:6231'}
        response = S.get(url)
        captchaId = re.findall("captchaId: '(.*?)',", response.text.replace("\n", ""))[0]
        callback = "cx_captcha_function"
        timestap = str(int(time.time() * 1000))
        nonce = getNonce()
        captchaKey = getMd5(timestap + nonce)
        token = getMd5(timestap + captchaId + 'slide' + captchaKey) + f':{int(timestap) + 300000}'
        url = "https://captcha.chaoxing.com/captcha/get/verification/image"

        params = {
            "callback": callback,
            "captchaId": captchaId,
            "type": "slide",
            "version": "1.1.20",
            "captchaKey": captchaKey,
            "token": token,
            "referer": url,
            "_": timestap
        }
        response = S.get(url, params=params, headers=self.headers)

        slider_img_url = re.findall(r'"cutoutImage":"(.*?)"', response.text.replace("\n", ""))
        background_img_url = re.findall(r'"shadeImage":"(.*?)"', response.text.replace("\n", ""))
        position = self.recognize_slider_captcha(slider_img_url[0], background_img_url[0])
        token = re.findall(r'"token":"(.*?)"', response.text.replace("\n", ""))[0]
        if position is not None:
            position = position["target"]
            url = "https://captcha.chaoxing.com/captcha/check/verification/result"
            params = {
                "callback": callback,
                "captchaId": captchaId,
                "type": "slide",
                "token": token,
                "textClickArr": json.dumps([{"x": position[0]}]),
                "coordinate": "[]",
                "runEnv": "10",
                "version": "1.1.20",
                "t": "a",
                "_": timestap
            }
            response = S.get(url, params=params, headers=self.headers)
            try:
                data_txt_2 = response.text.replace('false', 'False').replace('true', 'True')
                data_json_2 = re.findall(r"\((.*?)\)", data_txt_2)[0]
                data_2 = eval(data_json_2)
                extraData = json.loads(data_2['extraData'])['validate']
            except Exception as e:
                logger.debug(f"登录失败，原因：{e}")
                raise

            url = "https://www.blyun.com/login_dd.jsp"
            data = {
                "ecode": "utf-8",
                "send": "true",
                "backurl": "",
                "ddtype": "lib",
                "remember": "0",
                "validate": extraData,
                "UserName": "",
                "PassWord": "",
                "tyno": "",
                "UserName_lib": username,
                "PassWord_lib": self.string_to_base64(password),
                "userform": "mylibddrzbl",
                "UserName4": "",
                "PassWord4": "",
                "login": "login"
            }
            response = S.post(url, data=data, headers=self.headers, allow_redirects=True)
            response.encoding = "utf-8"
            if "百链学术搜索" in response.text:
                return True, S.cookies.get_dict()
        else:
            return False, None

    def login_run(self):
        for email in emails:
            username = email["username"]
            password = email["password"]
            try:
                login_status, cookies = self.login(username=username, password=password)
                if login_status:
                    email_address = email["email_address"]
                    cookies["email_address"] = email_address
                    self.add_cookie(username=username, cookie=cookies)
                    logger.info(f"登录成功，用户名：{username}")
            except Exception as e:
                logger.debug(f"登录失败，原因：{e}")


if __name__ == '__main__':
    login = LoginForBaiLian()
    login.login_run()
# 10.1149/1945-7111/ac8a1b